package com.lawson.survivor;

import android.app.ListActivity;
import android.content.ContentValues;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.RawContacts;
import android.telephony.SmsManager;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class SurvivorActivity extends ListActivity {

	public static final String GROUP_EMERGENCY = "Emergency";
	private static final String HTTP_MAPS_GOOGLE = "http://maps.google.com/?q=%1$s,%2$s&iwloc=near&ll=%1$s,%2$s";
	public static final int PICK_CONTACT = 1;
	private final int gpsTimeOut = 30*1000; //30 seconds.
	private static final String SMS_MESSAGE = "%s has sent this message in Emergency. Attached is a link link to their last know location. Map Link: %s";


	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		populateContacts();
		

		final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
		final Button btnSendSMS = (Button) findViewById(R.id.btnSOS);
		final Button btnAddContact= (Button) findViewById(R.id.btnAddContact);
		
		btnSendSMS.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				
				final String accuracyPreferenceValue = 
						sharedPrefs.getString(getString(R.string.preference_accuracy_key), getString(R.string.preference_accuracy_default_value));
				
				int accuracy = 0;
				try{
					accuracy = Integer.parseInt(accuracyPreferenceValue);
				} catch(NumberFormatException nfe) {
					//TODO Log the error.
				}
				
				LocationFinder locationFinder = new LocationFinder(SurvivorActivity.this, gpsTimeOut, 1000, accuracy);

				locationFinder.setOnLocationFoundListener(new LocationFindListener() {
				
					@Override
					public void onLocationFound(Location location) {

						final boolean sendSMS = sharedPrefs.getBoolean(getString(R.string.preference_sms_key), true);

						if (sendSMS){
							sendEmergencyMessage(location);
						}
					}
				});
			}
		});

		btnAddContact.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
				//intent.setType(android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
				startActivityForResult(intent, PICK_CONTACT);
			}
		});
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		// TODO Auto-generated method stub
		super.onListItemClick(l, v, position, id);
	}

	/**
	 * Obtains the contact list for the currently selected account.
	 *
	 */
	private void populateContacts(){
		Cursor group =  getEmergencyGroup();
		int numberOfContacts = 0; 
		final TextView textViewGroupCount = (TextView) findViewById(R.id.textViewGroupCount);
		
		if (group.moveToFirst()){	
		    long groupId = group.getLong(group.getColumnIndex(ContactsContract.Groups._ID));
			
			getContentResolver().query(ContactsContract.Data.CONTENT_URI, new String[] { ContactsContract.Data.RAW_CONTACT_ID },
				    ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID+"="+groupId,
				    null, null);
			
			Uri uri = ContactsContract.Data.CONTENT_URI;
			String[] projection = new String[] {
					ContactsContract.Data._ID,
					ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID,
					ContactsContract.Data.RAW_CONTACT_ID,
					ContactsContract.Data.CONTACT_ID,
					ContactsContract.Data.DISPLAY_NAME
			};
			String selection = ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID + " = " + groupId;
			
			Cursor contacts = managedQuery(uri, projection, selection, null, null);
			numberOfContacts = contacts.getCount();
			
			String[] fields = new String[] {ContactsContract.Data.DISPLAY_NAME};
			ListAdapter adapter = new SimpleCursorAdapter(this, R.layout.contact_entry, contacts, fields, new int[] {R.id.textViewContactName});
			adapter.registerDataSetObserver(new DataSetObserver() {
				
				@Override
				public void onChanged() {
					super.onChanged();
					//registered to track changed
					textViewGroupCount.setText(String.format(getString(R.string.textViewGroupCount),String.valueOf(getListAdapter().getCount())));
				}
			});
	
			ListView listView = getListView();
			listView.setItemsCanFocus(false);
			setListAdapter(adapter);

		}

		textViewGroupCount.setText(String.format(getString(R.string.textViewGroupCount),String.valueOf(numberOfContacts)));
	}

	private void sendEmergencyMessage(Location location) {

		final SmsManager smsManager = SmsManager.getDefault();
		final Uri uri = Uri.parse(String.format(HTTP_MAPS_GOOGLE, location.getLatitude(), location.getLongitude()));
	
		Cursor selectedContacts = ((SimpleCursorAdapter)this.getListView().getAdapter()).getCursor();
		selectedContacts.moveToFirst();

		do {
			final String rawContactId = selectedContacts.getString(selectedContacts.getColumnIndex(ContactsContract.Data.CONTACT_ID));
			
			Cursor selectedRealContacts = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, new String[]{ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME}, ContactsContract.Contacts._ID + "=?",
					new String[]{rawContactId}, null);
			
			
			while (selectedRealContacts.moveToNext()) {
				final String id = selectedRealContacts.getString(selectedRealContacts.getColumnIndex(ContactsContract.Contacts._ID));
				
				final String displayName = selectedRealContacts.getString(selectedRealContacts.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

				Cursor phoneNumbers = 
						getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null);

				while (phoneNumbers.moveToNext()) {

					final String message = String.format(SMS_MESSAGE, displayName, uri.toString());
					final int phoneType = 
							phoneNumbers.getInt(phoneNumbers.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
					//TODO suppress Multiple messages to phones.
					if (phoneType == Phone.TYPE_MOBILE) {
						String mobilePhoneNumber = phoneNumbers.getString(phoneNumbers.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
						smsManager.sendTextMessage(mobilePhoneNumber,null,message, null, null);
					}
				}
				phoneNumbers.close();
			}
			selectedRealContacts.close();

		} while (selectedContacts.moveToNext());  
	} 

	@Override
	protected void onResume() {
		super.onResume();
	}

	@Override
	protected void onPause() {
		super.onPause();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return true;
	}

	@Override
	public void onActivityResult(int reqCode, int resultCode, Intent data) {
		super.onActivityResult(reqCode, resultCode, data);
		
		if(reqCode == PICK_CONTACT && resultCode == RESULT_OK){			
			Uri uri = data.getData();
			Cursor selectedContact = managedQuery(uri, null, null, null, null);

			while (selectedContact.moveToNext()) {	
				//Get Contact Raw ID
				String id = selectedContact.getString(selectedContact.getColumnIndex(ContactsContract.Contacts._ID));		
				Cursor contact = getContentResolver().query(RawContacts.CONTENT_URI, new String[]{RawContacts._ID}, RawContacts.CONTACT_ID + "=?",
						new String[]{id}, null);
			
				Cursor contactGroup = getEmergencyGroup();
				
				if (contact.moveToFirst() && contactGroup.moveToFirst()) {
					//Add Contact to group
				    long rawContactId = contact.getLong(contact.getColumnIndex(RawContacts._ID));
				    long groupId = contactGroup.getLong(contactGroup.getColumnIndex(ContactsContract.Groups._ID));
				    
				    if (!isContactInGroup(groupId, rawContactId)){
						ContentValues values = new ContentValues();
					    values.put(ContactsContract.CommonDataKinds.GroupMembership.RAW_CONTACT_ID, rawContactId); 
					    values.put(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID,groupId);
					    values.put(ContactsContract.CommonDataKinds.GroupMembership.MIMETYPE,ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE);
					    getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
				    }
				} else{
					Toast.makeText(this, "Error: Contact Not Added.", 5000);
				}
				contact.close();
				contactGroup.close();
			}
		}
	}
	
	/**
	 * Returns a which holds the Emergency group row of 'Emergency' contacts. The method will generate the group if it doesn't exist.
	 * @return A record of the 'Emegency' group used to store the 'Emergency' contacts.
	 */
	private Cursor getEmergencyGroup(){
		//Add 'Emergency' group if needed.
		final String[] groupProjection = new String[] {ContactsContract.Groups._ID, ContactsContract.Groups.DELETED};
		String groupSelection = String.format(ContactsContract.Groups.TITLE +" = '%s' AND " + ContactsContract.Groups.DELETED+"=0" , GROUP_EMERGENCY);
		Cursor contactGroup = managedQuery(ContactsContract.Groups.CONTENT_URI, groupProjection, groupSelection, null, null);
		
		if (contactGroup.getCount() == 0){
			ContentValues groupValues = new ContentValues();
			groupValues.put(ContactsContract.Groups.TITLE, GROUP_EMERGENCY);
			groupValues.put(ContactsContract.Groups.GROUP_VISIBLE,1);
			getContentResolver().insert(ContactsContract.Groups.CONTENT_URI, groupValues);
			contactGroup.requery(); //requery so cursor can be used with groupid.
		}
		return contactGroup;
	}
	
	private boolean isContactInGroup(long groupId, long rawContactId){
	    String[] projection = new String[] {
                ContactsContract.CommonDataKinds.GroupMembership.RAW_CONTACT_ID};
	    
	    String where = ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID + "="
                + groupId + " AND "
                + ContactsContract.CommonDataKinds.GroupMembership.MIMETYPE + "='"
                + ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE + "' AND "
                + ContactsContract.CommonDataKinds.GroupMembership.RAW_CONTACT_ID +"="+rawContactId;
	    
        Cursor contactGroup = getContentResolver().query(
                ContactsContract.Data.CONTENT_URI, projection, where, null, null);
        
        boolean isContactInGroup = (contactGroup.getCount() > 0);
        contactGroup.close();
        
        return isContactInGroup;
	}


	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.settings_option_item:
			startActivity(new Intent(this, SurvivorPreferenceActivity.class));
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}
}